/*
 * Copyright (c) 2016-2021, Hangzhou Qulian Technology Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "CuTest.h"
#include "x509.h"
#include "ql_type.h"

// Declare internal functions
OhErrType Base64Encode(OhByteType* dst, OhSizeType dlen, OhSizeType *olen, OhByteType* src, OhSizeType slen);

// Test case
void key_parse_test_right(CuTest* tc) {
    OhByteType srcData[] = "-----BEGIN EC PRIVATE KEY-----\n"
                             "MHQCAQEEIDyNfgAOpTNKqB430x0Vg7IioUcoUrC8ORC0WcURbu++oAcGBSuBBAAK\n"
                             "oUQDQgAEAabMhAWKawZAFURHbzPZJlUexoLyvhx9bBMBAH94mU5F8ZgEV1fJL9iV\n"
                             "LPMBIrtYFIyubrVNH5I5ww0Hj4embQ==\n"
                             "-----END EC PRIVATE KEY-----";
    X509KeyType key;
    KeyInit(&key);
    OhErrType res = KeyParse(&key, srcData);
    KeyFree(&key);

    CuAssertIntEquals(tc, X509_SUCCESS, res);
}

void key_parse_test_wrong_curve(CuTest* tc) {
    OhByteType srcData[] = "-----BEGIN EC PRIVATE KEY-----\n"
                           "MHcCAQEEIHpF5aQ5fcDYmtaCIGkb6gPUxYjDbOhnLKPM9dtUPdAxoAoGCCqGSM49\n"
                           "AwEHoUQDQgAEaTgeworBiIEf1uomYNAJMTaUHQ++VCkDkZIg+csD3MsnYtnHVBOK\n"
                           "tO9yc1w5qrOYm0a6LGu4hOuvOFDQsvoBtQ==\n"
                           "-----END EC PRIVATE KEY-----";
    X509KeyType key;
    KeyInit(&key);
    OhErrType res = KeyParse(&key, srcData);
    KeyFree(&key);

    CuAssertIntEquals(tc, X509_ERR_PARSE_CURVE_MISMATCH, res);
}

void key_parse_test_wrong_key_format(CuTest* tc) {
    OhByteType srcData[] = "MHcCAQEEIHpF5aQ5fcDYmtaCIGkb6gPUxYjDbOhnLKPM9dtUPdAxoAoGCCqGSM49\n"
                               "AwEHoUQDQgAEaTgeworBiIEf1uomYNAJMTaUHQ++VCkDkZIg+csD3MsnYtnHVBOK\n"
                               "tO9yc1w5qrOYm0a6LGu4hOuvOFDQsvoBtQ==\n"
                               "-----END EC PRIVATE KEY-----";
    X509KeyType key;
    KeyInit(&key);
    OhErrType res = KeyParse(&key, srcData);
    KeyFree(&key);

    CuAssertIntEquals(tc, X509_ERR_PARSE_NO_FIND_SYMBAL, res);
}

void key_parse_test_wrong_key_format_2(CuTest* tc) {
    OhByteType srcData[] = "-----BEGIN EC PRIVATE KEY-----\n"
                           "MHcCAQEEIHpF5aQ5fcDYmtaCIGkb6gPUxYjDbOhnLKPM9dtUPdAxoAoGCCqGSM49\n"
                           "AwEHoUQDQgAEaTgeworBiIEf1uomYNAJMTaUHQ++VCkDkZIg+csD3MsnYtnHVBOK\n"
                           "tO9yc1w5qrOYm0a6LGu4hOuvOFDQsvoBtQ==\n";
    X509KeyType key;
    KeyInit(&key);
    OhErrType res = KeyParse(&key, srcData);
    KeyFree(&key);

    CuAssertIntEquals(tc, X509_ERR_PARSE_NO_FIND_SYMBAL, res);
}

void base64_encode_test(CuTest* tc) {
    OhByteType  dst_buffer2[500];
    OhByteType template[] = {
                        0x30,0x74,0x02,0x01,0x01,0x04,0x20,0x00, // priv key
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,
                        0x07,0x06,0x05,0x2b,0x81,0x04,0x00,0x0a,
                        0xa1,0x44,0x03,0x42,0x00,0x04,0x00,0x00, // pub key
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x00,0x00,0x00,0x00,0x00,0x00};
    OhByteType pri[] = { 0x02,0x02,0x02,0x01,0x01,0x01,0x01,0x01,
                        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
                        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
                        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
    OhByteType pub[] = { 0xc5,0x42,0xb4,0x16,0xff,0x48,0xd8,0x1b,
                        0xe1,0x65,0x1f,0x25,0x54,0x8c,0x06,0xd1,
                        0x91,0xcf,0xa3,0x0c,0xb8,0x1a,0xf5,0x19,
                        0x11,0x83,0x0c,0xf2,0xe0,0x12,0xcc,0x9f,
                        0xf7,0xfd,0x76,0xdd,0xd1,0x59,0x4c,0x60,
                        0x71,0x60,0xa9,0x79,0x04,0x33,0x15,0x19,
                        0x24,0x00,0x63,0x91,0x6d,0x8f,0x36,0x1d,
                        0xef,0x53,0x89,0x73,0x0a,0xc2,0xd7,0x44};
    memcpy(template + 7,pri,32);
    memcpy(template + 54,pub,64);
    OhSizeType dst_len2;
    Base64Encode(dst_buffer2, sizeof(dst_buffer2), &dst_len2, template, 118);

    CuAssertStrEquals(tc, "MHQCAQEEIAICAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBoAcGBSuBBAAKoUQDQgAExUK0Fv9I2BvhZR8lVIwG0ZHPowy4GvUZEYMM8uASzJ/3/Xbd0VlMYHFgqXkEMxUZJABjkW2PNh3vU4lzCsLXRA==", (char*)dst_buffer2);
}

CuSuite* x509_test_suite(void)
{
    CuSuite* suite = CuSuiteNew();
    SUITE_ADD_TEST(suite, key_parse_test_right);
    SUITE_ADD_TEST(suite, key_parse_test_wrong_curve);
    SUITE_ADD_TEST(suite, key_parse_test_wrong_key_format);
    SUITE_ADD_TEST(suite, key_parse_test_wrong_key_format_2);
    SUITE_ADD_TEST(suite, base64_encode_test);
    return suite;
}